package com.photoeditor.demo.ui.widget.image;

import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;

import com.edmodo.cropper.CropImageView;


/**
 * 用于实现旋转的动画
 */
public class AnimationCropImageView extends CropImageView {

    private Drawable mDrawable;

    public AnimationCropImageView(Context context) {
        super(context);
    }

    public AnimationCropImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private static final String DEGREES_ROTATED = "DEGREES_ROTATED";
    private int mDegreesRotated = 0;
    private float mDegree = 0;
    private float mDegreeX = 0;
    private float mDegreeY = 0;
    private int mFlipDuration = 300;
    private int mRotationDuration = 200;
    private Matrix mMatrix = null;
    private ObjectAnimator mObjectAnimator;
    private float mValue = 1;

    public void setMatrix(Matrix matrix) {
        restoreImageView();
        this.mMatrix = new Matrix(matrix);
    }

    @Override
    public void setImageDrawable(BitmapDrawable dbitmap) {
        super.setImageDrawable(dbitmap);
    }

    @Override
    public void setImageBitmap(final Bitmap bitmap) {
        super.setImageBitmap(bitmap);
    }

    /**
     * 将ImageView复原
     */
    public void restoreImageView() {
        if (mObjectAnimator != null) {
            mObjectAnimator.end();
        }
        mImageView.setRotation(0);
        mImageView.setRotationX(0);
        mImageView.setRotationY(0);
        mImageView.setScaleX(1);
        mImageView.setScaleY(1);
        mValue = 1;
        mDegree = 0;
        mDegreeX = 0;
        mDegreeY = 0;
        mMatrix = null;
        mDegreesRotated = 0;
    }

    /**
     * 获取到通过变换后的图片
     *
     * @return
     */
    public Bitmap getRotationBitmap() {
        Matrix matrix = new Matrix();
        if (mDegreeX == 180 && mDegreeY == 180) {
            matrix.postScale(-1, -1);
            matrix.postTranslate(getBitmap().getWidth(), getBitmap().getHeight());
        } else if (mDegreeX == 180) {
            matrix.postScale(1, -1);
            matrix.postTranslate(0, getBitmap().getHeight());
        } else if (mDegreeY == 180) {
            matrix.postScale(-1, 1);
            matrix.postTranslate(getBitmap().getWidth(), 0);
        }

        if (mDegree != 0) {
            matrix.preRotate(mDegree);
        }

        int bh = getBitmap().getWidth();
        int bw = getBitmap().getHeight();
        int absDegrees = Math.abs((int) mDegree);
        if (bw < mImageView.getWidth() && bh < mImageView.getHeight() && (absDegrees == 90 || absDegrees == 270)) {//这种情况需要转向
            float w;
            float h;
            w = mImageView.getWidth();
            h = w * ((float) bh / (float) bw);
            if (h > mImageView.getHeight()) {
                h = mImageView.getHeight();
                w = h * ((float) bw / (float) bh);
            }
            matrix.postScale(w / bw, h / bh);
        }
        Bitmap bitmap = Bitmap.createBitmap(getBitmap(), 0, 0, getBitmap().getWidth(), getBitmap().getHeight(), matrix, true);
        return bitmap;
    }

    /**
     * 如果是横向的图  则是小图  旋转动画是 ： 0.x -> 1 -> 0.x
     * 如果是纵向的图  则是大图  旋转动画是 ： 1 -> 0.x -> 1
     *
     * @param degrees
     */
    public void rotationImageView(int degrees) {
        if (mMatrix == null) return;

        mDrawable = this.mImageView.getDrawable();
        Rect r = mDrawable.getBounds();
        //真实宽高
        int bitmapW = r.width();
        int bitmapH = r.height();
        float[] values1 = new float[10];
        mMatrix.getValues(values1);
        //旋转前当前显示的宽高
        float bw = (bitmapW * values1[0]);
        float bh = (bitmapH * values1[4]);


        degrees = degrees % 360;
        int d = (int) ((mDegree + degrees) % 360);
        int absDegrees = Math.abs(d);
        if ((absDegrees == 90 || absDegrees == 270)) {
            float temp = bh;
            bh = bw;
            bw = temp;
        }
        int absd = Math.abs(degrees);
        if ((absd == 90 || absd == 270)) {
            int temp = bitmapW;
            bitmapW = bitmapH;
            bitmapH = temp;
        }
        PropertyValuesHolder pvsX = null;
        PropertyValuesHolder pvsY = null;
        if (bw > mImageView.getWidth() || bh > mImageView.getHeight()) {//这种情况需要缩小
            float w;
            float h;
            w = mImageView.getWidth();
            h = w * ((float) bh / (float) bw);
            if (h > mImageView.getHeight()) {
                h = mImageView.getHeight();
                w = h * ((float) bw / (float) bh);
            }
            if (mValue != 1) {//1.x->1缩小
                float sx = bw / w;
                float sy = bh / h;
                mValue = 1f;
                mMatrix.postScale(1.0f / sx, 1.0f / sy);
                pvsX = PropertyValuesHolder.ofFloat("scaleX", sx, 1f);
                pvsY = PropertyValuesHolder.ofFloat("scaleY", sy, 1f);
            } else {//1->0.x缩小
                float sx = w / bw;
                float sy = h / bh;
                mValue = sx;
                mMatrix.postScale(sx, sy);
                pvsX = PropertyValuesHolder.ofFloat("scaleX", 1f, sx);
                pvsY = PropertyValuesHolder.ofFloat("scaleY", 1f, sy);
            }

        } else if (bw < mImageView.getWidth() && bh < mImageView.getHeight()) {//这种情况需要放大
            float w;
            float h;
            w = mImageView.getWidth();
            h = w * ((float) bh / (float) bw);
            if (h > mImageView.getHeight()) {
                h = mImageView.getHeight();
                w = h * ((float) bw / (float) bh);
            }
            if (mValue == 1) {//1->1.x放大
                float sx = w / bw;
                float sy = h / bh;
                mValue = sx;
                mMatrix.postScale(sx, sy);
                pvsX = PropertyValuesHolder.ofFloat("scaleX", 1f, sx);
                pvsY = PropertyValuesHolder.ofFloat("scaleY", 1f, sy);
            } else {//0.x->1放大
                float sx = bw / w;
                float sy = bh / h;
                mValue = 1f;
                mMatrix.postScale(1.0f / sx, 1.0f / sy);
                pvsX = PropertyValuesHolder.ofFloat("scaleX", sx, 1f);
                pvsY = PropertyValuesHolder.ofFloat("scaleY", sy, 1f);
            }
        }
        if (pvsX != null) {
            PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", mDegree, mDegree + degrees);
            mObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(mImageView, rotation, pvsX, pvsY).setDuration(mRotationDuration);
            mObjectAnimator.start();
        } else {
            mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "rotation", mDegree, mDegree + degrees).setDuration(mRotationDuration);
            mObjectAnimator.start();
        }
        mDegree = (mDegree + degrees) % 360;
        mDegreesRotated = (int) mDegree;
    }

    /**
     * 翻转
     *
     * @param isHorizontal
     */
    public void flipImageView(boolean isHorizontal) {
        if (!isHorizontal) {
            mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "rotationX", mDegreeX, mDegreeX + 180f).setDuration(mFlipDuration);
            mObjectAnimator.start();
            mDegreeX = (mDegreeX + 180f) % 360;
            mDegreesRotated = -2;
        } else {
            mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "rotationY", mDegreeY, mDegreeY + 180f).setDuration(mFlipDuration);
            mObjectAnimator.start();
            mDegreeY = (mDegreeY + 180f) % 360;
            mDegreesRotated = -1;
        }
    }

    @Override
    public Parcelable onSaveInstanceState() {
        final Bundle bundle = new Bundle();

        bundle.putParcelable("instanceState", super.onSaveInstanceState());
        bundle.putInt(DEGREES_ROTATED, mDegreesRotated);

        return bundle;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {

        if (state instanceof Bundle) {

            final Bundle bundle = (Bundle) state;
            mDegreesRotated = bundle.getInt(DEGREES_ROTATED);
            if (mDegreesRotated == -1) {
                flipImageView(true);
            } else if (mDegreesRotated == -2) {
                flipImageView(false);
            } else {
                int tempDegrees = mDegreesRotated;
                rotationImageView(mDegreesRotated);
                mDegreesRotated = tempDegrees;
            }
            super.onRestoreInstanceState(bundle.getParcelable("instanceState"));
        } else {
            super.onRestoreInstanceState(state);
        }
    }

    public Drawable getDrawable() {
        return mImageView.getDrawable();
    }

    public Matrix getImageMatrix() {
        return mImageView.getImageMatrix();
    }
}
